const bcrypt = require('bcryptjs');
const db = require('../models');
const { generateToken } = require('../utils/jwt');
const redis = require('../config/redis');
const WechatUtil = require('../utils/wechat');

const User = db.User;

/**
 * 用户控制器
 */
const userController = {
  /**
   * 用户注册
   * @param {Object} req 请求对象
   * @param {Object} res 响应对象
   * @param {Function} next 下一个中间件
   */
  async register(req, res, next) {
    try {
      const { username, password, email } = req.body;
      
      // 检查用户名是否已存在
      const existingUser = await User.findOne({ where: { username } });
      if (existingUser) {
        return res.status(400).json({
          code: 400,
          message: '用户名已存在'
        });
      }
      
      // 检查邮箱是否已存在
      if (email) {
        const existingEmail = await User.findOne({ where: { email } });
        if (existingEmail) {
          return res.status(400).json({
            code: 400,
            message: '邮箱已被使用'
          });
        }
      }
      
      // 加密密码
      const hashedPassword = await bcrypt.hash(password, 10);
      
      // 创建用户
      const newUser = await User.create({
        username,
        password: hashedPassword,
        email,
        lastLoginAt: new Date()
      });
      
      // 生成JWT令牌
      const token = await generateToken({ id: newUser.id, username: newUser.username });
      
      res.status(201).json({
        code: 0,
        message: '注册成功',
        data: {
          id: newUser.id,
          username: newUser.username,
          email: newUser.email,
          token
        }
      });
    } catch (error) {
      next(error);
    }
  },
  
  /**
   * 用户登录
   * @param {Object} req 请求对象
   * @param {Object} res 响应对象
   * @param {Function} next 下一个中间件
   */
  async login(req, res, next) {
    try {
      const { username, password } = req.body;
      
      // 查找用户
      const user = await User.findOne({ where: { username } });
      if (!user) {
        return res.status(401).json({
          code: 401,
          message: '用户名或密码错误'
        });
      }
      
      // 验证密码
      const isPasswordValid = await bcrypt.compare(password, user.password);
      if (!isPasswordValid) {
        return res.status(401).json({
          code: 401,
          message: '用户名或密码错误'
        });
      }
      
      // 更新最后登录时间
      await user.update({ lastLoginAt: new Date() });
      
      // 生成JWT令牌
      const token = await generateToken({ id: user.id, username: user.username });
      
      res.json({
        code: 0,
        message: '登录成功',
        data: {
          id: user.id,
          username: user.username,
          token
        }
      });
    } catch (error) {
      next(error);
    }
  },
  
  /**
   * 微信登录
   * @param {Object} req 请求对象
   * @param {Object} res 响应对象
   * @param {Function} next 下一个中间件
   */
  async wxLogin(req, res, next) {
    try {
      const { code } = req.body;
      
      // 获取微信用户信息
      const wxUserInfo = await WechatUtil.getUserInfo(code);
      
      // 查找或创建用户
      let user = await User.findOne({ where: { openId: wxUserInfo.openid } });
      
      if (!user) {
        // 创建新用户
        user = await User.create({
          username: wxUserInfo.nickname || `wx_user_${wxUserInfo.openid.substring(0, 8)}`,
          openId: wxUserInfo.openid,
          unionId: wxUserInfo.unionid,
          avatar: wxUserInfo.headimgurl,
          lastLoginAt: new Date()
        });
      } else {
        // 更新用户信息和登录时间
        await user.update({
          avatar: wxUserInfo.headimgurl,
          lastLoginAt: new Date()
        });
      }
      
      // 生成JWT令牌
      const token = await generateToken({ id: user.id, username: user.username });
      
      res.json({
        code: 0,
        message: '登录成功',
        data: {
          id: user.id,
          username: user.username,
          token
        }
      });
    } catch (error) {
      next(error);
    }
  },
  
  /**
   * 获取用户信息
   * @param {Object} req 请求对象
   * @param {Object} res 响应对象
   * @param {Function} next 下一个中间件
   */
  async getUserInfo(req, res, next) {
    try {
      const userId = req.user.id;
      
      const user = await User.findByPk(userId, {
        attributes: ['id', 'username', 'email', 'avatar', 'openId', 'createdAt', 'totalGames', 'completedGames', 'bestRecords']
      });
      
      if (!user) {
        return res.status(404).json({
          code: 404,
          message: '用户不存在'
        });
      }
      
      res.json({
        code: 0,
        message: '获取用户信息成功',
        data: user
      });
    } catch (error) {
      next(error);
    }
  },
  
  /**
   * 更新用户信息
   * @param {Object} req 请求对象
   * @param {Object} res 响应对象
   * @param {Function} next 下一个中间件
   */
  async updateUserInfo(req, res, next) {
    try {
      const userId = req.user.id;
      const { username, email, avatar, password } = req.body;
      
      // 查找用户
      const user = await User.findByPk(userId);
      if (!user) {
        return res.status(404).json({
          code: 404,
          message: '用户不存在'
        });
      }
      
      // 更新数据
      const updateData = {};
      
      if (username && username !== user.username) {
        // 检查用户名是否已存在
        const existingUser = await User.findOne({ where: { username } });
        if (existingUser) {
          return res.status(400).json({
            code: 400,
            message: '用户名已存在'
          });
        }
        updateData.username = username;
      }
      
      if (email && email !== user.email) {
        // 检查邮箱是否已存在
        const existingEmail = await User.findOne({ where: { email } });
        if (existingEmail) {
          return res.status(400).json({
            code: 400,
            message: '邮箱已被使用'
          });
        }
        updateData.email = email;
      }
      
      if (avatar) {
        updateData.avatar = avatar;
      }
      
      if (password) {
        // 加密密码
        updateData.password = await bcrypt.hash(password, 10);
      }
      
      // 更新用户信息
      await user.update(updateData);
      
      res.json({
        code: 0,
        message: '更新用户信息成功'
      });
    } catch (error) {
      next(error);
    }
  },
  
  /**
   * 用户登出
   * @param {Object} req 请求对象
   * @param {Object} res 响应对象
   * @param {Function} next 下一个中间件
   */
  async logout(req, res, next) {
    try {
      const authHeader = req.headers.authorization;
      
      if (authHeader && authHeader.startsWith('Bearer ')) {
        const token = authHeader.split(' ')[1];
        
        // 将令牌加入黑名单，过期时间与令牌相同
        const decoded = req.user;
        const exp = decoded.exp;
        const now = Math.floor(Date.now() / 1000);
        const ttl = exp - now;
        
        if (ttl > 0) {
          await redis.set(`blacklist:${token}`, '1', { EX: ttl });
        }
      }
      
      res.json({
        code: 0,
        message: '登出成功'
      });
    } catch (error) {
      next(error);
    }
  },
  
  /**
   * 获取微信JS API配置
   * @param {Object} req 请求对象
   * @param {Object} res 响应对象
   * @param {Function} next 下一个中间件
   */
  async getWxConfig(req, res, next) {
    try {
      const { url } = req.query;
      
      if (!url) {
        return res.status(400).json({
          code: 400,
          message: '缺少url参数'
        });
      }
      
      const config = await WechatUtil.getJsApiConfig(url);
      
      res.json({
        code: 0,
        message: '获取微信JS API配置成功',
        data: config
      });
    } catch (error) {
      next(error);
    }
  }
};

module.exports = userController;
